﻿using System;
using System.Configuration;
using System.Linq;
using SharpShare.Configuration;
using SharpShare.Afp.Protocol;

namespace SharpShare.Afp.Configuration {
    public class AuthenticationElement : ConfigurationElement, Protocol.IAfpUserManager {
        [ConfigurationProperty("groups")]
        public GenericElementCollection<GroupElement> Groups {
            get {
                return (GenericElementCollection<GroupElement>)this["groups"];
            }
        }

        [ConfigurationProperty("users")]
        public GenericElementCollection<UserElement> Users {
            get {
                return (GenericElementCollection<UserElement>)this["users"];
            }
        }

        #region IAfpUserManager Members

        string Protocol.IAfpUserManager.GetGroup(System.Guid id) {
            return this.Groups.Where(g => g.Identifier == id).Select(g => g.Name).FirstOrDefault();
        }

        System.Guid? Protocol.IAfpUserManager.GetGroup(string name) {
            return this.Groups.Where(g => g.Name == name).Select(g => (Guid?)g.Identifier).FirstOrDefault();
        }

        Protocol.IAfpUser Protocol.IAfpUserManager.GetUser(System.Guid id) {
            UserElement element = this.Users.Where(u => u.Identifier == id).FirstOrDefault();
            if (element == null)
                return null;
            return new User() { UserElement = element, AuthenticationElement = this };
        }

        Protocol.IAfpUser Protocol.IAfpUserManager.GetUser(string name) {
            UserElement element = this.Users.Where(u => u.Name == name).FirstOrDefault();
            if (element == null)
                return null;
            return new User() { UserElement = element, AuthenticationElement = this };
        }

        #endregion

        private class User : IAfpUser {

            public UserElement UserElement { get; set; }
            public AuthenticationElement AuthenticationElement { get; set; }

            #region IAfpUser Members

            public string Name {
                get { return this.UserElement.Name; }
            }

            public Guid Id {
                get { return this.UserElement.Identifier; }
            }

            public Guid PrimaryGroup {
                get {
                    string firstGroupName = this.UserElement.Groups.Cast<string>().FirstOrDefault();
                    if (firstGroupName == null)
                        return Guid.Empty;
                    return ((IAfpUserManager)this.AuthenticationElement).GetGroup(firstGroupName) ?? Guid.Empty;
                }
            }

            public bool IsInGroup(Guid groupId) {
                string name = ((IAfpUserManager)this.AuthenticationElement).GetGroup(groupId);
                if (name == null)
                    return false;
                return this.UserElement.Groups.Contains(name);
            }

            public bool Authenticate(string password) {
                return (this.UserElement.Password == password);
            }

            public bool CanChangePassword {
                get { return this.UserElement.CanChangePassword; }
            }

            public bool ChangePassword(string newPassword) {
                this.UserElement.Password = newPassword;
                return true;
            }

            #endregion
        }
    }
}
